package TS::PMT;

use strict;
use Scalar::Util qw(weaken);

use constant TABLE_PMT => 0x02;

sub new {
	my($pkg, $buffer) = @_;

	my $hash = {
		buffer => $buffer,

		table_id => undef,
		section_syntax_indicator => undef,
		private_indicator => undef,
		section_length => undef,
		program_number => 0,
		version_number => 0,
		current_next_indicator => 0,
		section_number => 0,
		last_section_number => 0,
		PCR_PID => undef,
		program_info_length => undef,
		descriptor => [],
		program => [],
		CRC_32 => undef,
	};

	my $s = bless $hash, $pkg;

	weaken($s->{buffer});
	$s->parse();

	return $s;
}

sub parse {
	my($s) = @_;

	$s->{table_id} = $s->{buffer}->getInt();

	if ($s->{table_id} == TABLE_PMT) {
		$s->pmt();
	} else {
		printf "#### no support table_id: 0x%02x\n", $s->{table_id};
#		exit;
	}
}

sub pmt {
	my($s) = @_;

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$s->{section_syntax_indicator}	= $a >> 7 & 0x01;
	$s->{private_indicator}			= $a >> 6 & 0x01;
	$s->{section_length}			= ($a & 0x0F) << 8 | $b;
	my $program_endbyte = $s->{buffer}->{pos} + $s->{section_length};

	if ($s->{section_syntax_indicator}) {
		$s->{program_number} = $s->{buffer}->getShort();

		my $a = $s->{buffer}->getInt();
		$s->{version_number} = $a >> 1 & 0x1F;
		$s->{current_next_indicator} = $a & 0x01;

		$s->{section_number} = $s->{buffer}->getInt();
		$s->{last_section_number} = $s->{buffer}->getInt();
	}

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$s->{PCR_PID} = ($a & 0x1F) << 8 | $b;

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$s->{program_info_length} = ($a & 0x0F) << 8 | $b;
	my $descriptor_endbyte = $s->{buffer}->{pos} + $s->{program_info_length};

	while ($s->{buffer}->{pos} + 1 < $descriptor_endbyte) {
		push(@{$s->{descriptor}}, TS::Descriptor::parse($s->{buffer}));
	}

	while ($s->{buffer}->{pos} + 4 < $program_endbyte - 4) {
		push(@{$s->{program}}, $s->program());
	}

	$s->{CRC_32} = $s->{buffer}->getLong();

	$s->{buffer}->{pos} = $program_endbyte;
}

sub program {
	my($s) = @_;

	my $ret = {};

	$ret->{stream_type} = $s->{buffer}->getInt();

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$ret->{elementary_PID} = ($a & 0x1F) << 8 | $b;

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$ret->{ES_info_length} = ($a & 0x0F) << 8 | $b;
	my $descriptor_endbyte = $s->{buffer}->{pos} + $ret->{ES_info_length};

	$ret->{descriptor} = [];

	while ($s->{buffer}->{pos} + 1 < $descriptor_endbyte) {
		push(@{$ret->{descriptor}}, TS::Descriptor::parse($s->{buffer}));
	}

	return $ret;
}

1;
